/**
 * 
 */
package easyservice.interpreter;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import easyservice.EasyServiceException;
import easyservice.protocol.Command;
import easyservice.protocol.CommandEnum;
import easyservice.protocol.FaultCommand;
import easyservice.protocol.NotifyCommand;
import easyservice.protocol.RequestCommand;
import easyservice.protocol.ResponseCommand;

/**
 * Interprets command.
 * 
 * @author Taciano Pinheiro
 * @author Rodrigo Barbosa Lira
 * 
 */
public class CommandInterpreter {

	/**
	 * Interprets a command.
	 * @param msg
	 * @return
	 */
	public static Command interpret(String msg) {
		StringTokenizer tokenizer = new StringTokenizer(msg);
		return start(tokenizer);
	}
	
	/**
	 * Start the interpreter process.
	 * @param result
	 * @param tokenizer 
	 * @throws EasyServiceException 
	 */
	private static Command start(StringTokenizer tokenizer) throws EasyServiceException {
		String initSimbol = tokenizer.nextToken();
		if (!initSimbol.equals("#")) {
			throw new EasyServiceException("Command need start with '#'");
		}
		return message(tokenizer);
	}

	/**
	 * Process a message
	 * @param tokenizer 
	 * @param result 
	 * @throws EasyServiceException 
	 */
	private static Command message(StringTokenizer tokenizer) throws EasyServiceException {
		String commandEnum = tokenizer.nextToken();

		// FIXME remove toString need
		try {
			if (commandEnum.equals(CommandEnum.REQUEST.toString()))
				return requestBody(tokenizer);
			else if (commandEnum.equals(CommandEnum.RESPONSE.toString()))
				return responseBody(tokenizer);
			else if (commandEnum.equals(CommandEnum.NOTIFY.toString()))
				return notifyBody(tokenizer);
			else if (commandEnum.equals(CommandEnum.FAULT.toString()))
				return faultBody(tokenizer);
		} catch (NoSuchElementException e) {
			throw new EasyServiceException("Syntax error");
		}
		return null;
	}

	/**
	 * Process the request command body
	 * @param tokenizer 
	 * @param result 
	 */
	private static Command requestBody(StringTokenizer tokenizer) {
		String method = tokenizer.nextToken();
		// read params, if exists
		List<String> params = new ArrayList<String>();
		params(tokenizer, params);
		return new RequestCommand(method, params);
	}
	
	/**
	 * Process the response command body
	 * @param tokenizer 
	 * @param result 
	 * @throws EasyServiceException 
	 */
	private static Command responseBody(StringTokenizer tokenizer) {
		String value = tokenizer.nextToken();
		return new ResponseCommand(value);
	}

	/**
	 * Process the notify command body.
	 * @param tokenizer 
	 * @param result 
	 */
	private static Command notifyBody(StringTokenizer tokenizer) {
		String method = tokenizer.nextToken();
		// read params, if exists
		List<String> params = new ArrayList<String>();
		params(tokenizer, params);
		return new NotifyCommand(method, params);
	}
	
	/**
	 * Process param from a command
	 * @param tokenizer 
	 * @param result 
	 */
	private static void params(StringTokenizer tokenizer, List<String> params) {
		String param;
		while (tokenizer.hasMoreTokens()) {
			param = tokenizer.nextToken();
			params.add(param);
			params(tokenizer, params);
		}
	}
	
	/**
	 * Process the fault command body.
	 * @param tokenizer 
	 * @param result 
	 * @throws EasyServiceException 
	 */
	private static Command faultBody(StringTokenizer tokenizer) {
		String faultType, message;
		faultType = tokenizer.nextToken();
		message = tokenizer.nextToken();
		return new FaultCommand(faultType, message);
	}
}
